package com.example.demo.common;

import com.auth0.jwt.JWT;
import com.auth0.jwt.JWTVerifier;
import com.auth0.jwt.algorithms.Algorithm;
import com.auth0.jwt.exceptions.JWTDecodeException;
import com.auth0.jwt.interfaces.DecodedJWT;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Component;

import java.util.Date;
import java.util.HashMap;
import java.util.Map;

/**
 * @author zhaiding
 * @since 2019/5/1
 */
@Component
public class JwtUtils {

    private static long expireTime;

    private static String secret;

    private static final String USERNAME = "username";

    public JwtUtils(@Value("${jwt.expireTime}") long expireTime, @Value("${jwt.secret}") String secret) {
        JwtUtils.expireTime = expireTime;
        JwtUtils.secret = secret;
    }

    /**
     * JWT生成Token.<br/>
     * <p>
     * JWT构成: header, payload, signature
     *
     * @param username 用户名
     * @return 加密的token
     */
    public static String sign(String username) {
        // header Map
        Map<String, Object> map = new HashMap<>(2);
        map.put("alg", "HS256");
        map.put("typ", "JWT");

        Date date = new Date();
        // 过期时间
        Date expiresDate = new Date(date.getTime() + expireTime * 1000 * 60);

        Algorithm algorithm = Algorithm.HMAC256(secret);

        // build token
        // param backups {iss:Service, aud:APP}
        return JWT.create()
                // header
                .withHeader(map)
                // payload
                .withClaim(USERNAME, username)
                // sign time
                .withIssuedAt(date)
                // expire time
                .withExpiresAt(expiresDate)
                // signature
                .sign(algorithm);

    }


    /**
     * 获得token中的信息无需secret解密也能获得
     *
     * @return token中包含的用户名
     */
    public static String getUsername(String token) {
        try {
            DecodedJWT jwt = JWT.decode(token);
            return jwt.getClaim(USERNAME).asString();
        } catch (JWTDecodeException e) {
            return null;
        }
    }

    /**
     * 校验token是否正确
     *
     * @param token 密钥
     * @return 是否正确
     */
    public static boolean verify(String token, String username) {
        try {
            Algorithm algorithm = Algorithm.HMAC256(secret);
            JWTVerifier verifier = JWT.require(algorithm)
                    .withClaim(USERNAME, username)
                    .build();
            DecodedJWT jwt = verifier.verify(token);
            return true;
        } catch (Exception e) {
            return false;
        }
    }
}
